#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "tbb/tbb.h"

//#define EPS 0.000001
//#define EPS 0.0000001
//#define EPS 0.000000000000001
#define EPS 0.00000000000001
#define MAX_JUMP 0.5
#define N 205
#define M 11

#include "vectorHistory.h"
#include "scalarHistory.h"
#include "OptimFunc.h"
#include "testFunctions.h"
#include "matrixFunctions.h"
#include "funcProps.h"
#include "minDirected.h"
#include "lbfgsPartial.h"
#include "bfgs.h"
#include "lbfgs.h"

void testVectorHistory(){
    Vector v1 = {1,2,3};
    Vector v2 = {4,2,1};
    Vector v3 = {5,3,7};
    Vector v4 = {6,4,1};
    Vector v5 = {7,8,9};
    VectorHistory vh;
    vhInit(&vh);
    vhPrint(&vh);
    vhPush(&vh, v1);
    vhPrint(&vh);
    vhPush(&vh, v2);
    vhPrint(&vh);
    vhPush(&vh, v3);
    vhPrint(&vh);
    vhPush(&vh, v4);
    vhPrint(&vh);
    vhPush(&vh, v5);
    vhPrint(&vh);
    vhPush(&vh, v2);
    vhPrint(&vh);
}

void testScalarHistory(){
    ScalarHistory sh;
    shInit(&sh);
    shPush(&sh, 1);
    shPrint(&sh);
    shPush(&sh, 2);
    shPrint(&sh);
    shPush(&sh, 3);
    shPrint(&sh);
    shPush(&sh, 4);
    shPrint(&sh);
    shPush(&sh, 5);
    shPrint(&sh);
    shPush(&sh, 6);
    shPrint(&sh);
    shPush(&sh, 7);
    shPrint(&sh);
}

static struct timeval tm1;

static inline void start()
{
    gettimeofday(&tm1, NULL);
}

static inline void stop()
{
    struct timeval tm2;
    gettimeofday(&tm2, NULL);

    unsigned long long t = 1000 * (tm2.tv_sec - tm1.tv_sec) + (tm2.tv_usec - tm1.tv_usec) / 1000;
    printf("%llu ms\n", t);
}

int main()
{
    double *x = malloc(sizeof(double) * N);
    double *x0 = malloc(sizeof(double) * N);
    int i;
    for (i=0; i<N; ++i){
        x[i] = 0;
        x0[i] = 1;
    }

    printV("x0", x0, N);
    printf("f(x0) = %g\n", n17QuarticFunction(x0, N));
	start();
//    #pragma omp parallel for shared(x,x0) private(i)
    for(i=0;i<2;++i){
        lbfgs(n17QuarticFunction, N, x, x0, 20);
    }

    printV("x", x, N);
    printf("f(x) = %g\n", n17QuarticFunction(x, N));
	stop();

    free(x0);
    free(x);

    //testVectorHistory();
    //testScalarHistory();

    return 0;
}
